interface User {
  name: string,
  age: number,
  email: string
}

type PartialUser = Partial<User>
type PickUser = Pick<User, 'name' | 'email'>

const au: PartialUser = {name: 'Jim'}
const pu: PickUser = {name: 'Jim', email: 'jim@gmail.com'}

// 自定义类型守卫：判断变量是否为数组
function isArray(value: unknown): value is any[] {
  return Array.isArray(value)
}

// 使用示例
const test1 = [1, 2, 3]
const test2 = "hello"
const test3 = { name: "John" }

console.log(isArray(test1)) // true
console.log(isArray(test2)) // false
console.log(isArray(test3)) // false

// 类型守卫的优势：在条件分支中，TypeScript 会缩小类型
function processValue(value: unknown) {
  if (isArray(value)) {
    // 在这个分支中，TypeScript 知道 value 是数组类型
    console.log("这是一个数组，长度为:", value.length)
    value.forEach(item => console.log(item))
  } else {
    // 在这个分支中，TypeScript 知道 value 不是数组
    console.log("这不是数组:", value)
  }
}

processValue([1, 2, 3])
processValue("hello")

interface Product {
  id: number;
  name: string;
  price: number;
  tags?: string[];
}

type PickProduct = Pick<Product, 'name' | 'price'>
type OmitProduct = Omit<Product, 'tags'>

type Fish = { swim: () => void }
type Bird = { fly: () => void }
type Human = { swim?: () => void; fly?: () => void }

// in运算符缩小
function move(animal: Fish | Bird | Human) {
  if ('swim' in animal) {
    return animal.swim?.()
  }
  return animal.fly?.()
}

// instanceof缩小
function logValue(value: Date | string) {
  if (value instanceof Date) {
    console.log(value.toUTCString())
  } else {
    console.log(value.toUpperCase())
  }
}

// 控制流分析
function example() {
  let x: string | number | boolean;
 
  x = Math.random() < 0.5;
  console.log(x); // let x: boolean

  if (Math.random() < 0.5) {
    x = "hello";
    console.log(x); // let x: string
  } else {
    x = 100;
    console.log(x); // let x: number
  }
 
  return x; // let x: string | number
}

// 使用类型谓词

export {}